/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hilton.tigershark.view;

import android.content.Context;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;

import com.hilton.tigershark.BrowserActivity;
import com.hilton.tigershark.R;

public class FindDialog extends WebDialog implements TextWatcher {
    private static final String TAG = "FindDialog";

    private TextView        mMatches;
    // Views with which the user can interact.
    private EditText        mEditText;
    private View            mNextButton;
    private View            mPrevButton;
    private View            mMatchesView;

    // When the dialog is opened up with old text, enter needs to be pressed
    // (or the text needs to be changed) before WebView.findAll can be called.
    // Once it has been called, enter should move to the next match.
    private boolean         mMatchesFound;
    private int             mNumberOfMatches;
    private int mIndexOfMatches;

    private View.OnClickListener mFindListener = new View.OnClickListener() {
        public void onClick(View v) {
            findNext();
        }
    };

    private View.OnClickListener mFindPreviousListener = new View.OnClickListener() {
        public void onClick(View v) {
            findPrevious();
        }
    };

    private void disableButtons() {
        mPrevButton.setEnabled(false);
        mNextButton.setEnabled(false);
        mPrevButton.setFocusable(false);
        mNextButton.setFocusable(false);
    }

    private void enableButtons() {
        mPrevButton.setFocusable(true);
        mNextButton.setFocusable(true);
        mPrevButton.setEnabled(true);
        mNextButton.setEnabled(true);
    }
    
    public FindDialog(BrowserActivity context) {
        super(context);
        LayoutInflater factory = LayoutInflater.from(context);
        factory.inflate(R.layout.browser_find, this);

        addCancel();
        mEditText = (EditText) findViewById(R.id.edit);
        
        View button = findViewById(R.id.next);
        button.setOnClickListener(mFindListener);
        mNextButton = button;
        
        button = findViewById(R.id.previous);
        button.setOnClickListener(mFindPreviousListener);
        mPrevButton = button;
        
        mMatches = (TextView) findViewById(R.id.matches);
        mMatchesView = findViewById(R.id.matches_view);
        disableButtons();

    }

    /**
     * Called by BrowserActivity.closeDialog.  Start the animation to hide
     * the dialog, inform the WebView that the dialog is being dismissed,
     * and hide the soft keyboard.
     */
    public void dismiss() {
        super.dismiss();
        mWebView.clearMatches();
        hideSoftInput();
    }
    
    public void show() {
        super.show();
        // Start the find dialog newly
        mMatchesView.setVisibility(View.GONE);
        mEditText.setText("");
        mEditText.requestFocus();
        mEditText.addTextChangedListener(this);
        mMatchesFound = false;
        mIndexOfMatches = 0;
        mNumberOfMatches = 0;
        disableButtons();
        final InputMethodManager imm = (InputMethodManager) mBrowserActivity
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED);
    }
    
    // TextWatcher methods
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }
    
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        findAll();
    }
    
    @Override
    public void afterTextChanged(Editable s) {
    }

    @Override
    public boolean dispatchKeyEventPreIme(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            KeyEvent.DispatcherState state = getKeyDispatcherState();
            if (state != null) {
                int action = event.getAction();
                if (KeyEvent.ACTION_DOWN == action
                        && event.getRepeatCount() == 0) {
                    state.startTracking(event, this);
                    return true;
                } else if (KeyEvent.ACTION_UP == action
                        && !event.isCanceled() && state.isTracking(event)) {
                    mBrowserActivity.closeDialogs();
                    return true;
                }
            }
        }
        return super.dispatchKeyEventPreIme(event);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        int keyCode = event.getKeyCode();
        if (event.getAction() == KeyEvent.ACTION_UP) {
            if (keyCode == KeyEvent.KEYCODE_ENTER && mEditText.hasFocus()) {
                if (mMatchesFound) {
                    findNext();
                } else {
                    findAll();
                    // Set the selection to the end.
                    Spannable span = (Spannable) mEditText.getText();
                    Selection.setSelection(span, span.length());
                }
                return true;
            }
        }
        return super.dispatchKeyEvent(event);
    }
    
    public void setText(String text) {
        mEditText.setText(text);
        findAll();
    }
    
    private void findAll() {
        if (mWebView == null) {
            throw new AssertionError("No WebView for FindDialog::findAll");
        }
        final CharSequence pattern = mEditText.getText();
        if (0 == pattern.length()) {
            disableButtons();
            mWebView.clearMatches();
            mMatchesView.setVisibility(View.GONE);
        } else {
            int found = mWebView.findAll(pattern.toString());
            mMatchesFound = true;
            setMatchesFound(found);
            if (found < 2) {
                disableButtons();
            } else {
                enableButtons();
            }
        }
    }
    
    private void setMatchesFound(int found) {
        mNumberOfMatches = found;
        if (found > 0) {
            mIndexOfMatches = 1;
        }
        updateMatchesString();
    }

    private void findNext() {
        if (mWebView == null) {
            throw new AssertionError("No WebView for FindDialog::findNext");
        }
        mWebView.findNext(true);
        if (mIndexOfMatches < mNumberOfMatches) {
            mIndexOfMatches++;
        }
        refreshMatchesResult();
    }

    private void findPrevious() {
        if (mWebView == null) {
            throw new AssertionError("No WebView for FindDialog::findPrevious");
        }
        mWebView.findNext(false);
        if (mIndexOfMatches > 1) {
            mIndexOfMatches--;
        }
        refreshMatchesResult();
    }
    
    private void refreshMatchesResult() {
        updateMatchesString();
        hideSoftInput();
    }

    private void updateMatchesString() {
        mMatchesView.setVisibility(View.VISIBLE);
        String result;
        if (mNumberOfMatches <= 0) {
            result = mBrowserActivity.getString(R.string.zero_match);
        } else if (mNumberOfMatches == 1) {
            result = mBrowserActivity.getString(R.string.one_match);
        } else {
            result = mBrowserActivity.getString(R.string.few_matches, mIndexOfMatches, mNumberOfMatches);
        }
        mMatches.setText(result);
    }
}